package com.foolishbird.sdk.core;

import android.accounts.NetworkErrorException;


import com.foolishbird.sdk.handler.ResponseHanderInterface;
import com.foolishbird.sdk.params.PostRequestParams;
import com.foolishbird.sdk.requester.HttpRequester;
import com.foolishbird.sdk.utils.IoUtils;
import com.foolishbird.sdk.utils.WL;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.atomic.AtomicBoolean;



public final class HttpEngineTask implements Runnable {

    private static final String TAG = HttpEngineTask.class.getSimpleName();

    private final HttpEngineInfo engineInfo;
    private final HttpRequester httpRequester;
    private final ResponseHanderInterface handler;
    private final int taskCount;

    private AtomicBoolean isCanceled = new AtomicBoolean(false);

    private HttpEngineTask(HttpEngineInfo engineInfo){
        this.httpRequester = engineInfo.requester;
        this.handler = engineInfo.handler;
        this.engineInfo = engineInfo;
        taskCount = EngineTaskCount.init();
    }

    public static HttpEngineTask createHttpGetEngineTask(String url, ResponseHanderInterface handler){
        return createHttpEngineTask(url, HttpRequester.Method.GET, null, handler);
    }

    public static HttpEngineTask createHttpPostEngineTask(String url, PostRequestParams requestParams, ResponseHanderInterface handler){
        return createHttpEngineTask(url, HttpRequester.Method.POST, requestParams, handler);
    }

    protected static HttpEngineTask createHttpEngineTask(String url, HttpRequester.Method method, PostRequestParams requestParams, ResponseHanderInterface handler){
        HttpEngineInfo httpEngineInfo = new HttpEngineInfo(HttpEngineApi.getInstance().configuration, url, method, requestParams, handler);
        return new HttpEngineTask(httpEngineInfo);
    }

    public final int getCurrentTaskId(){
        return taskCount;
    }

    public final void cancel(){
        isCanceled.set(true);
    }

    private void checkTaskCancelled() throws TaskCancelledException {
        if (isTaskInterrupted() || isCancelledTask()) {
            throw new TaskCancelledException();
        }
    }

    private boolean isTaskInterrupted() {
        if (Thread.interrupted()) {
            WL.d(TAG, "isTaskInterrupted ---> Thread is interrupted.");
            return true;
        }
        return false;
    }

    private boolean isCancelledTask(){
        return isCanceled.get();
    }

    @Override
    public void run() {
        if(handler != null) handler.onSendRequest(taskCount);
        StringBuilder builder = new StringBuilder();
        InputStream inputStream = null;
        InputStreamReader reader = null;
        try {
            inputStream = httpRequester.getInputStream(engineInfo.url, engineInfo.httpMethod, engineInfo.requestParams);
            reader = new InputStreamReader(inputStream, "utf-8");

            checkTaskCancelled();

            char[] buffer = new char[1024];
            int lenght = 0;
            while((lenght = reader.read(buffer)) != -1){
                builder.append(buffer, 0, lenght);
                checkTaskCancelled();
            }
            String responString = builder.toString();
            responString = responString.replace(",\"data\":\"{}\"","");
            responString = responString.replace(",\"data\":\"[]\"","");
            responString = responString.replace(",\"data\":[]","");
//            responString = responString.replace("[]","{}");
            if(handler != null) handler.onResponseSuccess(taskCount, responString);
            WL.d(TAG, "run ---> response result: " + builder.toString());
        } catch (NetworkErrorException e) {
            WL.e(TAG, "run ---> NetworkErrorException: " + e.getLocalizedMessage());
            if(handler != null) handler.onNetworkException(taskCount, e);
        } catch (UnsupportedEncodingException e) {
            WL.e(TAG, "run ---> UnsupportedEncodingException");
            if(handler != null) handler.onException(taskCount, e);
        } catch (IOException e) {
            WL.e(TAG, "run ---> IOException: " + e.getLocalizedMessage());
            if(handler != null) handler.onException(taskCount, e);
        } catch (TaskCancelledException e) {
            WL.e(TAG, "run ---> TaskCancelledException");
            if(handler != null) handler.onCancel(taskCount);
        } finally {
            IoUtils.closeSilently(reader);
            IoUtils.closeSilently(inputStream);
            HttpEngineApi.getInstance().cancel(taskCount);
        }
    }

    private static class EngineTaskCount {
        private static int count = 0;

        public static int init(){
            if(++count < 0) {
                count = 0;
            }
            return count;
        }

    }

    static class TaskCancelledException extends Exception {
    }

}
